import { Router } from 'express';
import { TEXT_CONSTANTS } from '../constants';
import { Exchange, User } from '../models_nosql';
import { Ticker_SQL, Spread_SQL } from '../models_sql';
import { dbConnectMySQL } from '../utilities';
import { Op, sql } from 'sequelize';
import {
	getArraySortedByProp,
	startHandlerAllTickers,
	startALLAccessBlockchain,
	getTimestamps,
	getArrFundRatesDetailed,
	getArrayUniqueValues,
	getObjExchangeById
} from '../common';
import {
	CONSTANTS_BT,
	CONSTANTS_MG,
	CONSTANTS_BG,
	CONSTANTS_BM,
	CONSTANTS_XT,
} from '../constants';

export const additionalsRouter = Router();

// start screener'ов
additionalsRouter.post('/get-data-tickers', async (req, res) => {
	const { userId, arrExchanges } = req.body;
	// const user = await User.findOne({ _id: userId });
	let message = 'Screener started!';
	let success = true;

	// logging times
	const getLogTimes = (params) => {
		const { nameFunc, startTime, endTime, stTm, edTm } = params;
		const diff = (edTm - stTm) / (1000 * 60);
		console.log(
			`${nameFunc}\n 0_Time: ${startTime} \n 1_Time: ${endTime} \n result: ${diff.toFixed(
				2
			)} minutes`
		);
	};

	const prm1 = {
		nameFunc: 'startALLAccessBlockchain',
		startTime: getTimestamps(),
		stTm: new Date(),
	};
	const params1 = {
		isWithdraw: false,
		isDeposit: false,
	};
	// await startALLAccessBlockchain(params1)
	getLogTimes({
		...prm1,
		endTime: getTimestamps(),
		edTm: new Date(),
	});

	const prm2 = {
		nameFunc: 'startHandlerAllTickers',
		startTime: getTimestamps(),
		stTm: new Date(),
	};
	const params2 = [{ typeMarket: 'SPOT' }, { typeMarket: 'FUT' }];
	await startHandlerAllTickers(params2);
	getLogTimes({
		...prm2,
		endTime: getTimestamps(),
		edTm: new Date(),
	});

	return res.status(200).send({
		message,
		success,
	});
});

// получение fundingRates
additionalsRouter.post('/get-funding-rates', async (req, res) => {
	const { typeQuery, arrExchanges } = req.body;

	const queryRates =
		arrExchanges.length === 0
			? {
				where: {
					fundRate: {
						[Op.or]: {
							[Op.gte]: 0.0025,
							[Op.lte]: -0.009,
						},
					},
				},
				order: [['fundRate', 'DESC']],
			}
			: {
				where: {
					[Op.and]: [
						{ baseAsset: { [Op.or]: arrExchanges } },
						{ typeMarket: 'FUT' },
					],
				},
				order: [['baseAsset', 'DESC']],
			};

	const rates = await Ticker_SQL.findAll(queryRates);
	let finalArray = [];

	const result =
		rates.length === 0
			? {
				message: 'getFundingRates Empty!',
				success: false,
			}
			: {
				message: `getFundingRates ${rates.length} Ok!`,
				success: true,
			};

	if (typeQuery === 'secondQuery') {
		finalArray = rates.filter((item) => {
			return item.fundHours !== '' || item.shortName === 'BX';
		});
		// console.log(finalArray)
		let arr = ['BT', 'MG', 'BG', 'BM', 'XT'];
		const objParams = {
			userId: '',
			prefix: '',
			apiKeys: '',
			requestHeader: '',
			constants: {},
			additionals: {},
		};

		for (let i = 0; i < arr.length; i++) {
			const filteredArr = rates.filter((item) => {
				return item.shortName === arr[i];
			});

			if (arr[i] === 'BT') {
				objParams.constants = CONSTANTS_BT;
			} else if (arr[i] === 'MG') {
				objParams.constants = CONSTANTS_MG;
			} else if (arr[i] === 'BG') {
				objParams.constants = CONSTANTS_BG;
			} else if (arr[i] === 'BM') {
				objParams.constants = CONSTANTS_BM;
			} else if (arr[i] === 'XT') {
				objParams.constants = CONSTANTS_XT;
			}

			if (filteredArr.length !== 0) {
				console.log(arr[i] + ': secondQuery | getArrFundRatesDetailed...');
				const fundRatesDetailed = await getArrFundRatesDetailed({
					...objParams,
					tickers: filteredArr,
				});
				finalArray = finalArray.concat(fundRatesDetailed);
			}
		}
		// console.log(finalArray);
	}

	return res.status(200).send({
		message: result.message,
		data: typeQuery === 'secondQuery' ? finalArray : rates,
		success: result.success,
	});
});

// получение spreads
additionalsRouter.post('/get-spreads', async (req, res) => {
	const { baseAsset, typeQuery } = req.body;
	
	const getQweryString = () =>{
		let qweryString
		if(typeQuery === "allSpreadsFromTickers"){
			qweryString = `SELECT
				market1.baseAsset "baseAsset",
				market1.exchange "spotExchange",
				market1.exchangeId "spotExchangeId",
				market1.askPrice "buyPrice",
				market1.createdAt "createdAt",
				market2.exchange "futExchange",
				market2.exchangeId "futExchangeId",
				market2.bidPrice "sellPrice",
				ROUND((( market2.bidPrice - market1.askPrice ) / 
				market2.bidPrice * 100), 2) "spread",
				ROUND((market2.fundRate * 100), 4) "fundRate"
				FROM tickers market1
				INNER JOIN tickers market2 
				ON market1.baseAsset = market2.baseAsset 
				AND market1.quoteAsset = "USDT" 
				AND market2.quoteAsset = "USDT" 
				AND market2.bidPrice > 0 
				AND market1.askPrice > 0
				WHERE market1.typeMarket = "SPOT" 
				AND market2.typeMarket = "FUT"   
				AND market2.shortName != "XT" 
				AND market1.shortName != "XG"
				AND((market2.bidPrice - market1.askPrice) / market2.bidPrice * 100) < 30 
				AND((market2.bidPrice - market1.askPrice) / market2.bidPrice * 100) > 3
				ORDER BY spread DESC`
		} else if(typeQuery === "baseAssetFromTickers"){
			qweryString = `SELECT
				market1.baseAsset "baseAsset",
				market1.exchange "spotExchange",
				market1.exchangeId "spotExchangeId",
				market1.askPrice "buyPrice",
				market1.createdAt "createdAt",
				market2.exchange "futExchange",
				market2.exchangeId "futExchangeId",
				market2.bidPrice "sellPrice",
				ROUND((( market2.bidPrice - market1.askPrice ) / 
				market2.bidPrice * 100), 2) 'spread', 
				ROUND((market2.fundRate * 100), 4) 'fundRate' 
				FROM tickers market1 
				INNER JOIN tickers market2 
				ON market1.baseAsset = '${baseAsset}'
				AND market2.baseAsset = '${baseAsset}'
				AND market1.quoteAsset = 'USDT' 
				AND market2.quoteAsset = 'USDT' 
				AND market2.bidPrice > 0 
				AND market1.askPrice > 0 WHERE market1.typeMarket = 'SPOT' 
				AND market2.typeMarket = 'FUT' ORDER BY spread DESC`;
		} else if(typeQuery === "baseAssetFromSpreads"){
			qweryString = `SELECT * FROM spreads WHERE baseAsset ='${baseAsset}'`
		}
		return qweryString
	} 

	const spreads = await dbConnectMySQL.query(getQweryString());
	let message = `${spreads[0].length} spreads getted!`;
	let success = true;

	return res.status(200).send({
		message,
		data: spreads.length !== 0 ? spreads[0] : [],
		success,
	});
});

// сохранение spreads в БД
additionalsRouter.post('/save-spreads', async (req, res) => {
	const { spreads } = req.body

	// если массив спредов пустой
	if (spreads.length === 0) {
		return res.status(200).send({
			success: false,
			message: `These spreads are empty`,
		});
	}
	// если массив спредов НЕ пустой
	else {
		await Spread_SQL.bulkCreate(spreads)
			.then(() => {
				return res.status(200).json({
					success: true,
					message: `${spreads.length} spreads saved`,
				});
			})
			.catch((err) => {
				console.log(err);
				return res.status(400).json({
					success: false,
					message: `Error saving spreads`,
				});
			});
	}
});
